package com.qys.livesMall.shop.controller.sys;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qys.livesMall.app.user.service.IH2AppUserBalanceService;
import com.qys.livesMall.common.constants.Constants;
import com.qys.livesMall.common.exception.QysException;
import com.qys.livesMall.common.result.R;
import com.qys.livesMall.common.utils.MessageUtils;
import com.qys.livesMall.finance.enums.AccountBusinessTypeEnum;
import com.qys.livesMall.finance.model.dto.FinancePayDTO;
import com.qys.livesMall.finance.service.FinanceBusinessService;
import com.qys.livesMall.framework.utils.SecurityUtils;
import com.qys.livesMall.framework.view.QysPage;
import com.qys.livesMall.shop.constants.OrderStatus;
import com.qys.livesMall.shop.constants.OrderType;
import com.qys.livesMall.shop.constants.PayMethod;
import com.qys.livesMall.shop.mapper.ShopGoodsSkuStocksMapper;
import com.qys.livesMall.shop.mapper.ShopOrderReturnApprovedMapper;
import com.qys.livesMall.shop.modal.dto.OrderReturnDto;
import com.qys.livesMall.shop.modal.dto.ShopOrderSkuDto;
import com.qys.livesMall.shop.modal.dto.shop.order.OrderReturnSearch;
import com.qys.livesMall.shop.modal.entity.*;
import com.qys.livesMall.shop.modal.query.OrderApproverQuery;
import com.qys.livesMall.shop.modal.vo.OrderHandelVO;
import com.qys.livesMall.shop.modal.vo.ShopOrderReturnVO;
import com.qys.livesMall.shop.service.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 *用户退货
 * </p>
 *
 * @author gmx
 * @since 2023-06-23
 */
@RestController
@RequestMapping("/sys/shopOrderReturnApproved")
@Tag(name = "sys-用户商品退货", description = "sys-用户商品退货")
public class SysShopOrderReturnApprovedController {
    private final Map<Long, Object> locks = new ConcurrentHashMap<>();

    @Resource
    private ShopOrderReturnApprovedService approvedService;
    @Resource
    private ShopOrderReturnProcessService processService;
    @Resource
    private ShopOrderInfoService infoService;
    @Resource
    private ShopOrderReturnExpressService expressService;
    @Resource
    private ShopOrderSkuService skuService;
    @Resource
    private H2ShopBaseService baseService;
    @Resource
    private ShopGoodsInfoService goodsInfoService;
    @Resource
    private ShopGoodsSkuService goodsSkuService;

    @Resource
    private ShopOrderReturnApprovedMapper approvedMapper;
    @Resource
    private ShopGoodsSkuStocksMapper skuStocksMapper;

    @Resource
    FinanceBusinessService financeBusinessService;

    @Autowired
    private ShopOrderStatusManager orderStatusManager;

    @Autowired
    private ShopOrderSettlementInfoService shopOrderSettlementInfoService;


    @PostMapping("/search")
    public R<QysPage<ShopOrderReturnVO>> search(@RequestBody OrderReturnSearch search){
        return R.ok(approvedService.search(search));
    }


    @Operation(summary = "退货信息详情")
    @GetMapping("/{id}")
    public R<OrderReturnDto> get(@PathVariable Long id){
        OrderReturnDto returnDto= approvedMapper.joinQueryById(id);
        Long orderSkuId = returnDto.getOrderSkuId();
        ShopOrderSku shopOrderSku = skuService.getById(orderSkuId);
        ShopOrderSkuDto skuDto = new ShopOrderSkuDto();
        ShopGoodsSku sku = goodsSkuService.getById(shopOrderSku.getSkuId());
        ShopGoodsInfo goods = goodsInfoService.getById(sku.getShopGoodsId());
        BeanUtil.copyProperties(shopOrderSku,skuDto);
        skuDto.setGoodsDesc(goods.getGoodsDesc());
        H2ShopBase shop = baseService.queryById(returnDto.getShopId());
        returnDto.setOrderSkuDto(skuDto);
        returnDto.setShopName(shop.getShopName());
        return R.ok(returnDto);
    }

    /**
     * 确认申请
     * @param handelVO
     * @return
     */
    @Operation(summary = "确认操作")
    @PostMapping("/confirmed")
    @Transactional(rollbackFor = {Exception.class})
    public R confirmed(@RequestBody OrderHandelVO handelVO){
        ShopOrderReturnApproved approved = approvedService.getById(handelVO.getApprovedId());
        if (!Objects.equals(approved.getStatus(),OrderStatus.ReturnStatus.APPLIED)){
            throw new QysException(MessageUtils.message("order.status.not.return"));
        }
        approved.setUpdateTime(LocalDateTime.now());
        if (Objects.equals(handelVO.getStatus(), Constants.YesNo.NO)){
            //不通过
            approved.setStatus(OrderStatus.ReturnStatus.NO_PASS);
            approved.setDescription(handelVO.getOpinion());
            if (!approvedService.updateById(approved))
                throw new QysException(MessageUtils.message("system.error.approved"));
            processService.add(approved.getId(), approved.getStatus(),handelVO.getOpinion(),approved.getType());

            //订单状态复原
            //订单状态
            ShopOrderSku shopOrderSku = skuService.getById(approved.getOrderSkuId());
            shopOrderSku.setOrderStatus(shopOrderSku.getReturnBeforeStatus());
            skuService.updateById(shopOrderSku);
            ShopOrderInfo orderInfo = infoService.getById(shopOrderSku.getOrderId());
            List<ShopOrderSku> skus = skuService.getStatusByOrderId(shopOrderSku.getOrderId());
            orderInfo.setOrderStatus(orderStatusManager.getMainOrderStatus(skus));
            infoService.updateById(orderInfo);
        }else {
            approved.setStatus(OrderStatus.ReturnStatus.CONFIRMED);
            try {
                if (!approvedService.updateById(approved))
                    throw new QysException(MessageUtils.message("system.error.approved"));
                processService.add(approved.getId(), approved.getStatus(),approved.getType());
                //订单状态
                ShopOrderSku shopOrderSku = skuService.getById(approved.getOrderSkuId());
                shopOrderSku.setOrderStatus(OrderStatus.RETURN_CONFIRMED);
                skuService.updateById(shopOrderSku);
                ShopOrderInfo orderInfo = infoService.getById(shopOrderSku.getOrderId());
                List<ShopOrderSku> skus = skuService.getStatusByOrderId(shopOrderSku.getOrderId());
                orderInfo.setOrderStatus(orderStatusManager.getMainOrderStatus(skus));
                infoService.updateById(orderInfo);

                if(Objects.equals(OrderType.ReturnType.REFUND,approved.getType())){
                    //进入待退款
                    approved.setStatus(OrderStatus.ReturnStatus.WAIT_REFUND);
                    if (!approvedService.updateById(approved))
                        throw new QysException(MessageUtils.message("system.error.approved"));
                }
            } catch (QysException e) {
                return R.fail(e.getMessage());
            }
        }
        return R.ok();
    }

    /**
     * 平台签收操作
     * @param handelVO
     * @return
     */
    @Operation(summary = "平台签收操作")
    @PostMapping("/platformSign")
    @Transactional(rollbackFor = {Exception.class})
    public R platformSign(@RequestBody OrderHandelVO handelVO){
        ShopOrderReturnApproved approved = approvedService.getById(handelVO.getApprovedId());
        if (Objects.equals(approved.getType(), OrderType.ReturnType.REFUND)){
            throw new QysException(MessageUtils.message("order.type.not.return"));
        }
        if (!Objects.equals(approved.getStatus(),OrderStatus.ReturnStatus.USER_SHIPPED)){
            throw new QysException(MessageUtils.message("order.status.not.return"));
        }
        approved.setUpdateTime(LocalDateTime.now());
        approved.setStatus(OrderStatus.ReturnStatus.PLATFORM_RECEIVED);
        try {
            if (!approvedService.updateById(approved))
                throw new QysException(MessageUtils.message("system.error.approved"));
            processService.add(approved.getId(),approved.getStatus(),approved.getType());
            if(Objects.equals(OrderType.ReturnType.RETURN,approved.getType())){
                //进入待退款
                approved.setStatus(OrderStatus.ReturnStatus.WAIT_REFUND);
                if (!approvedService.updateById(approved))
                    throw new QysException(MessageUtils.message("system.error.approved"));
            }
        }catch (QysException e){
            return R.fail(e.getMessage());
        }
        return R.ok();
    }

    /**
     * 平台发货操作
     * @param handelVO
     * @return
     */
    @Operation(summary = "平台发货操作")
    @PostMapping("/platformShipped")
    @Transactional(rollbackFor = {Exception.class})
    public R platformShipped(@RequestBody OrderHandelVO handelVO){
        ShopOrderReturnApproved approved = approvedService.getById(handelVO.getApprovedId());
        if (!Objects.equals(approved.getType(), OrderType.ReturnType.EXCHANGE)){
            throw new QysException(MessageUtils.message("order.type.not.return"));
        }
        if (!Objects.equals(approved.getStatus(),OrderStatus.ReturnStatus.PLATFORM_RECEIVED)){
            throw new QysException(MessageUtils.message("order.status.not.return"));
        }
        approved.setUpdateTime(LocalDateTime.now());
        approved.setStatus(OrderStatus.ReturnStatus.PLATFORM_SHIPPED);

        if (!approvedService.updateById(approved)) {
            throw new QysException(MessageUtils.message("system.error.approved"));
        }
        processService.add(approved.getId(),approved.getStatus(),approved.getType());
        //运单号
        ShopOrderReturnExpress exp =new ShopOrderReturnExpress();
        exp.setApprovedId(approved.getId());
        exp.setExpressNum(handelVO.getExpressNo());
        exp.setShipper(1);
        exp.setCreateTime(LocalDateTime.now());
        exp.setUpdateTime(LocalDateTime.now());
        expressService.save(exp);
        return R.ok();
    }

    /**
     * 退款操作
     * @param handelVO
     * @return
     */
    @Operation(summary = "退款操作")
    @PostMapping("/refund")
    @Transactional(rollbackFor = {Exception.class})
    public R refund(@RequestBody OrderHandelVO handelVO){
        ShopOrderReturnApproved approved = approvedService.getById(handelVO.getApprovedId());
        if (Objects.equals(approved.getType(), OrderType.ReturnType.EXCHANGE)){
            throw new QysException(MessageUtils.message("order.type.not.return"));
        }
        if (!Objects.equals(approved.getStatus(),OrderStatus.ReturnStatus.WAIT_REFUND)){
            throw new QysException(MessageUtils.message("order.status.not.return"));
        }
        approved.setUpdateTime(LocalDateTime.now());
        approved.setStatus(OrderStatus.ReturnStatus.RETURNED);
        if (!approvedService.updateById(approved))
            throw new QysException(MessageUtils.message("system.error.approved"));
        processService.add(approved.getId(),approved.getStatus(),approved.getType());
        //订单状态
        ShopOrderSku orderSku=skuService.getById(approved.getOrderSkuId());
        orderSku.setOrderStatus(OrderStatus.RETURNED);
        skuService.updateById(orderSku);
        //更新订单结算状态
        ShopOrderSettlementInfo settlementInfo=shopOrderSettlementInfoService.getByOrderId(orderSku.getId());
        if (settlementInfo!=null&&Objects.equals(settlementInfo.getStatus(), Constants.YesNoInt.NO)){
            settlementInfo.setStatus(2);
            shopOrderSettlementInfoService.updateById(settlementInfo);
        }

        ShopOrderInfo orderInfo=infoService.getById(orderSku.getOrderId());
        List<ShopOrderSku> skus= skuService.getByOrderId(orderSku.getOrderId());
        orderInfo.setOrderStatus(orderStatusManager.getMainOrderStatus(skus));
        infoService.updateById(orderInfo);
        //退款
        //判断是否退运费
        BigDecimal postage=new BigDecimal("0");
        if(Objects.equals(orderSku.getReturnBeforeStatus(),OrderStatus.UNSHIPPED)){
            //未发货，可能退运费
            List<ShopOrderSku> categorySkus = skus.stream()
                    .filter(o -> Objects.equals(o.getShopId(), orderSku.getShopId()))
                    .filter(o -> Objects.equals(o.getCategoryId(), orderSku.getCategoryId()))
                    .filter(o -> !Objects.equals(o.getId(),orderSku.getId()))
                    .collect(Collectors.toList());
            if (CollectionUtils.isEmpty(categorySkus)){
                postage=orderSku.getPostage();
            }else {
                for (ShopOrderSku temp:categorySkus){
                    if (Objects.equals(temp.getOrderStatus(),OrderStatus.UNSHIPPED)
                        ||Objects.equals(temp.getOrderStatus(),OrderStatus.SHIPPED)
                        ||Objects.equals(temp.getOrderStatus(),OrderStatus.RECEIVED)
                        ||Objects.equals(temp.getOrderStatus(),OrderStatus.RETURN_APPLIED)
                        ||Objects.equals(temp.getOrderStatus(),OrderStatus.RETURN_CONFIRMED)
                    ){
                        postage = BigDecimal.ZERO;
                        break;
                    }
                    if (Objects.equals(temp.getOrderStatus(),OrderStatus.RETURNED)){
                        if (Objects.equals(temp.getReturnBeforeStatus(),OrderStatus.UNSHIPPED)){
                            postage=orderSku.getPostage();
                        }
                    }
                }
            }
        }else {
            //已发货，不退运费
            postage=BigDecimal.ZERO;
        }

        BigDecimal moneys = orderSku.getMoney().add(postage);
        FinancePayDTO financePayDTO = new FinancePayDTO();
        financePayDTO.setUserId(approved.getReturnUserId());
        financePayDTO.setAmountIncurred(moneys);
        financePayDTO.setBusinessType(AccountBusinessTypeEnum.USER_ORDER_RETURN_AFTER);
        financePayDTO.setBusinessNo(orderSku.getSkuOrderId());
        if(orderSku.getSettlementStatus().equals("0")){
            financePayDTO.setBusinessType(AccountBusinessTypeEnum.USER_ORDER_RETURN_BEFORE);
        }
        financeBusinessService.pay(financePayDTO);
        if(!financePayDTO.getSuccess()){
            throw new QysException(financePayDTO.getMessage());
        }
        //退还货款
        if (orderSku.getSettlementStatus().equals("0")) {
            Integer num = orderSku.getNum();
            int stocksCount = skuStocksMapper.decount(orderSku.getStocksId(), -num);
            if(stocksCount<1){
                throw new QysException(MessageUtils.message("system.error.order"));
            }
            //如果是先款后货，不退货款
            if (!Objects.equals(orderSku.getCostPayType(), PayMethod.CostPayType.PURCHASE)&&Objects.equals(orderSku.getCostPay(), Constants.YesNoInt.YES)) {
                FinancePayDTO costPayDTO = new FinancePayDTO();
                costPayDTO.setShopId(orderSku.getShopId());
                costPayDTO.setAmountIncurred(orderSku.getCostPrice().multiply(new BigDecimal(orderSku.getNum())));
                if (Objects.equals(orderSku.getCostPayType(), PayMethod.CostPayType.EARNEST_MONEY)) {
                    //获取应缴保证金
                    BigDecimal earnestMoney=baseService.getPayableEarnestMoney(orderSku.getShopId());
                    if (costPayDTO.getAmountIncurred().compareTo(earnestMoney)==1){
                        //退还金额大于应缴保证金金额 退还到店铺余额
                        costPayDTO.setBusinessType(AccountBusinessTypeEnum.REFUND);
                    }else {
                        costPayDTO.setBusinessType(AccountBusinessTypeEnum.DEDUCTION_GOODS_PAY_RETURN_EARNEST_MONEY);
                    }
                }else {
                    costPayDTO.setBusinessType(AccountBusinessTypeEnum.REFUND);
                }
                costPayDTO.setBusinessNo(orderSku.getSkuOrderId());
                financeBusinessService.pay(costPayDTO);
                if (!financePayDTO.getSuccess()) {
                    throw new QysException(costPayDTO.getMessage());
                }
            }

        }
        return R.ok();
    }



    @GetMapping("/express/{id}")
    public R<ShopOrderReturnExpress> express(@PathVariable Long id){
        LambdaQueryWrapper<ShopOrderReturnExpress> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopOrderReturnExpress::getApprovedId,id);
        ShopOrderReturnExpress exp = expressService.getOne(queryWrapper);
        if (ObjectUtils.isEmpty(exp)){
            return R.fail(MessageUtils.message("no.waybill"));
        }
        return R.ok(exp);
    }

    @GetMapping("/process/{approvedId}")
    public R<List<ShopOrderReturnProcess>> process(@PathVariable("approvedId") Long approvedId){
        LambdaQueryWrapper<ShopOrderReturnProcess> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopOrderReturnProcess::getApprovedId,approvedId);
        queryWrapper.orderByDesc(ShopOrderReturnProcess::getCreateTime);
        List<ShopOrderReturnProcess> list = processService.list(queryWrapper);

        return R.ok(list);
    }
}
